/*
 ，
 
  * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2017年10月15日
 * <修改描述:>
 */
package com.tx.component.dailytask.executor;

import java.time.LocalDate;
import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.transaction.PlatformTransactionManager;

import com.tx.component.dailytask.task.IDailyTask;
import com.tx.component.task.annotations.TaskClass;
import com.tx.component.task.context.TaskContextImpl;
import com.tx.component.task.interceptor.TaskExecuteSession;
import com.tx.component.task.interceptor.TaskExecuteSessionUtils;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.util.DateUtils;

/**
 * 任务执行器的的抽象类实现
 * <功能详细描述>
 * 
 * @author  Tim.PengQY
 * @version  [版本号, 2017年10月16日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@TaskClass(method = "execute", parameterTypes = {
        LocalDate.class }, getIdMethodName = "getId", getParentIdMethodName = "getParentId", getNameMethodName = "getName", getRemarkMethodName = "getRemark", getExecutableMethodName = "isExecutable", getPriorityMethodName = "getPriority", getParametersMethodName = "getParameters")
public abstract class AbstractDailyTaskExecutor<TASK extends IDailyTask>
        implements DailyTaskExecutor {
    
    /** 日志记录器 */
    protected Logger logger = LoggerFactory.getLogger(TaskContextImpl.class);
    
    /** beanName */
    protected String beanName;
    
    /** 任务实例 */
    protected TASK task;
    
    /** 事务manager */
    @Resource
    protected PlatformTransactionManager transactionManager;
    
    /** <默认构造函数> */
    public AbstractDailyTaskExecutor() {
        super();
    }
    
    /** <默认构造函数> */
    public AbstractDailyTaskExecutor(String beanName, TASK task,
            PlatformTransactionManager transactionManager) {
        super();
        this.beanName = beanName;
        this.task = task;
        this.transactionManager = transactionManager;
    }
    
    /**
     * @param executeDate
     * @return
     */
    @Override
    public void execute(LocalDate date) {
        AssertUtils.notNull(date, "date is null.");
        AssertUtils.notNull(this.task, "task is null.");
        
        //获取执行会话
        TaskExecuteSession executeSession = TaskExecuteSessionUtils
                .getSession();
        
        //获取下次执行时间
        Date nextFireDate = executeSession.getNextFireDate();
        //下次执行时间没有设置的情况兼容运行
        //如果在上线新增任务期间期望在固定一个时间后才启动，可在注解中添加初始化的parameters,并在其中为其设置nextFireDate
        if (nextFireDate != null
                && nextFireDate.compareTo(DateUtils.toDate(date)) > 0) {
            //下次执行时间大于传入时间的则不用执行
            //下次执行时间小于或等于以为着可以进行执行
            executeSession.setSkipped();
            return;
        }
        
        //任务执行以后，并返回下次执行时间
        LocalDate nextDate = doExecute(date);
        //设置下次执行时间
        executeSession.setNextFireDate(DateUtils.toDate(nextDate));
    }
    
    /**
     * 执行每日定时任务<br/>
     * <功能详细描述>
     * @param executeLocalDate
     * @return [参数说明]
     * 
     * @return LocalDate [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    protected abstract LocalDate doExecute(LocalDate executeLocalDate);
    
    /**
     * @return
     */
    @Override
    public int getPriority() {
        AssertUtils.notNull(this.task, "task is null.");
        return this.task.getPriority();
    }
    
    /**
     * @return
     */
    @Override
    public Map<String, String> getParameters() {
        AssertUtils.notNull(this.task, "task is null.");
        return this.task.getParameters();
    }
    
    /**
     * @return
     */
    @Override
    public String getId() {
        AssertUtils.notNull(this.task, "task is null.");
        return this.task.getId();
    }
    
    /**
     * @return
     */
    @Override
    public String getParentId() {
        AssertUtils.notNull(this.task, "task is null.");
        return this.task.getParentId();
    }
    
    /**
     * @return
     */
    @Override
    public String getName() {
        AssertUtils.notNull(this.task, "task is null.");
        return this.task.getName();
    }
    
    /**
     * @return
     */
    @Override
    public String getRemark() {
        AssertUtils.notNull(this.task, "task is null.");
        return this.task.getRemark();
    }
    
    /**
     * @return
     */
    @Override
    public String getClassName() {
        AssertUtils.notNull(this.task, "task is null.");
        return AopUtils.getTargetClass(this.task).getName();
    }
    
    /**
     * @return 返回 beanName
     */
    @Override
    public String getBeanName() {
        return beanName;
    }
    
    /**
     * @param 对beanName进行赋值
     */
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
    
    /**
     * @param 对task进行赋值
     */
    public void setTask(TASK task) {
        this.task = task;
    }
    
    /**
     * @param 对transactionManager进行赋值
     */
    public void setTransactionManager(
            PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }
}
